package ru.sgu.diploma.practic.service.impl;


import org.apache.commons.lang.StringUtils;
import ru.sgu.diploma.practic.domain.model.Automat;
import ru.sgu.diploma.practic.domain.model.State;
import ru.sgu.diploma.practic.errors.AlphabetExcephion;
import ru.sgu.diploma.practic.errors.NoStartStateException;
import ru.sgu.diploma.practic.errors.NoStateFoundForNameException;
import ru.sgu.diploma.practic.service.AutomatGenerator;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * User: datmakin
 * Date: 13.03.11
 * Email: atmakin.dv@gmail.com
 */
public class AutomatGeneratorImpl implements AutomatGenerator{

    private String startStateMarker = "startstate";
    private String alphabetMarker = "alphabet";
    private Integer presentStateIndex = 1;
    private Integer nextStateIndex = 2;
    private Integer inputDateIndex = 0;
    private Integer ouputDateIndex = 3;

    public Automat generateAutomatFromFile(String input) throws IOException, NoStartStateException, AlphabetExcephion {
        StringReader sr = new StringReader(input);
        BufferedReader br = new BufferedReader(sr);
        return generateAutomatFromFile(br);
    }

    public Automat generateAutomatFromFile(BufferedReader buffer) throws IOException, NoStartStateException, AlphabetExcephion {

        String startStateName = "";
        String temp = "";

        Map<String, State> stateMap = new HashMap<String, State>();

        String[] alphabet = null;

        while((temp = buffer.readLine()) != null) {
            String raw[] = temp.split("\\;");
            if (raw.length < 2)
                continue;
            if (raw[0].equals(startStateMarker))
                startStateName = raw[1];
            if (raw[0].equals(alphabetMarker)) {
                alphabet = new String[raw.length - 1];
                for (int i = 1; i < raw.length; i++) {
                    alphabet[i - 1] = raw[i].trim();
                }
            }

            if (raw.length < 4)
                continue;

            State state;
            if (!stateMap.containsKey(raw[presentStateIndex])) {
                 state = new State(raw[presentStateIndex]);
            } else {
                state = stateMap.get(raw[presentStateIndex]);
            }

            state.getOutputs().put(raw[inputDateIndex], raw[ouputDateIndex]);
            state.getNextStates().put(raw[inputDateIndex], raw[nextStateIndex]);

            stateMap.put(state.getStateName(), state);
        }

        if (StringUtils.isEmpty(startStateName))
            throw new NoStartStateException("");
        if (alphabet == null)
            throw new AlphabetExcephion("no alphabet");

        Automat automat = new Automat();
        automat.setStateMap(stateMap);
        automat.setAlphabet(alphabet);
        try {
            automat.setStartState(startStateName);
        } catch (NoStateFoundForNameException e) {
            throw new NoStartStateException("no start state found for name: " + e.getMessage());
        }

        return automat;
    }
}
